import sys
import os
import re

from django.utils.translation import ugettext, ugettext_lazy as _

from multiprofiles import settings


class ProfileCollectorError(Exception):
    pass


class ProfileCollector:

    collected = False
    profiles = {}
    profiles_info = []

    _profile_pattern = re.compile(r'class (?P<id>\w*)Profile')
    _meta_pattern = re.compile(r'(?P<indent>\s*)class Meta')
    _meta_indent_pattern = re.compile(r'(?P<indent>\s*)(?P<content>.*)$')
    _verbose_name_pattern = re.compile(
        r'verbose_name\s*=\s*(_\()?[\'\"]{1}(?P<verbose>.*)[\'\"]{1}'
    )

    @staticmethod
    def _clear_name(class_name):
        return class_name.replace('Profile', '').lower()

    @staticmethod
    def gatherinfo():
        if ProfileCollector.profiles_info:
            return

        if settings.PROFILES_INFO:
            ProfileCollector.profiles_info = settings.PROFILES_INFO
            return

        _mip = ProfileCollector._meta_indent_pattern
        _vnp = ProfileCollector._verbose_name_pattern
        profiles_id = []
        profiles_verbose = []

        files = os.listdir(settings.PROFILES_MODEL_DIR)
        #files.remove('__init__.py')
        for fname in [f for f in files if f.endswith('.py')]:
             f = open(os.path.join(settings.PROFILES_MODEL_DIR, fname), 'r')
             try:
                 lines = [l.rstrip() for l in f.readlines() if l.rstrip()]
                 while lines:
                     line = lines.pop(0)
                     m = ProfileCollector._profile_pattern.search(line)
                     m_meta = ProfileCollector._meta_pattern.match(line)
                     if m:
                          id = m.group('id')
                          profiles_id.append(id.lower())
                     if m_meta:
                          base_indent = len(m_meta.group('indent'))
                          indent = base_indent + 1
                          verbose = None
                          while indent > base_indent and lines:
                              m_ind = _mip.match(lines.pop(0))
                              if not m_ind:
                                  continue
                              indent = len(m_ind.group('indent'))
                              m_vn = _vnp.search(m_ind.group('content'))
                              if m_vn:
                                  verbose = m_vn.group('verbose')
                          if not verbose:
                              verbose = id
                          profiles_verbose.append(_(verbose))
             finally:
                 f.close()
        ProfileCollector.profiles_info = zip(profiles_id, profiles_verbose)
        if not ProfileCollector.profiles_info:
            raise ProfileCollectorError('No profiles found. Please, add at least one.')

    @staticmethod
    def autodiscover(globals=globals(), locals=locals()):
        if ProfileCollector.collected:
             return

        print 'Collecting profiles...'
        ProfileCollector.collected = True

        if settings.PROFILES_MODELS:
            ProfileCollector.profiles = settings.PROFILES_MODELS
            return

        from models.core import Profile, ProfileManager
        sys.path.insert(0, settings.PROFILES_MODEL_DIR)

        profiles = []
        files = [
            f[:-3] for f in os.listdir(settings.PROFILES_MODEL_DIR) if \
            f.endswith('.py') and not f.startswith('_')
        ]
        for module in files:
            mod = __import__(
                '%s' % module, globals, locals, [], -1
            )
            profile_names = [
                attr for attr in dir(mod) if (
                    attr.endswith('Profile') and len(attr) > 7
                )
            ]
            profile_classes = [
                getattr(mod, profile_name) for profile_name in profile_names
            ]
            profile_names = map(ProfileCollector._clear_name, profile_names)
            profiles.extend(zip(profile_names, profile_classes))
        sys.path.pop(0)

        ProfileCollector.profiles = dict(profiles)
        del Profile